#include "../fe8.h"
#include "../gba_hack.h"

enum{
    status_partial_rain = 12,
    status_partial_snow = 13,
};

enum{
    state_dead = 1<<2,
};

struct local_weather_t{
    int8_t      x,y;
    u32         moves[4];       //0,默认移动,1雨天，2雪天
    uint64_t    row[0x20];      //角色移动，最高15格，每格站2bit
};

typedef struct{
    int num;
    u32 data[0]
}log_t;
log_t *const log = 0x0;

struct local_weather_t * const local_weather = 0x203fc00;

static int set_local_weather(int x,int y,int v){
    local_weather->x = 0;       //设置已经初始化
    uint64_t *ptr = &local_weather->row[(y+15)];
    uint64_t vv = v&0x3;
    ptr[0] |= vv<<(x+15)*2;
}

static int get_local_weather(int x,int y){
    x -= local_weather->x;
    y -= local_weather->y;
    uint64_t *ptr = &local_weather->row[(y+15)];
    return (ptr[0]>>(x+15)*2) & 3;
}

static int abs(int v){
    if(v<0){
        return -v;
    }
    return v;
}

u32 JMP8018A60_r1(u32 unit){
    if(get(unit+0xc)&0x800){
        return 0x8860170;
    }
    int type = getb(0x202BCEC+0x15);
    if(type>=1){
        if(type<=2){
            return  get(get(unit+4)+0x40);  //雪天
        }
        else if(type==4){
            return get(get(unit+4)+0x3c);   //雨天
        }
    }
    //置为0
    gba_memset(local_weather,0,sizeof(*local_weather));
    local_weather->x = -1;
    local_weather->moves[1] = get(get(unit+4)+0x3c);
    local_weather->moves[2] = get(get(unit+4)+0x40);  //雪天

    //如果是普通天气，则处理单位影响
    //获得当前单位偏移
    int x,y;
    x = getb(unit+0x10);
    y = getb(unit+0x11);

    u32 dis = x+y;
    int range = 6;
    //处理我方单位
    int i = 1;
    int unit_side[6] = {
            1,63,
        0x81,191,
        0x41,127,
    };
    u32 *unit2 = 0x85C2A50;
    int idx = 0;
    for(idx=0;idx<3;idx++){
        int max = unit_side[idx*2+1];
        i   =   unit_side[idx*2+0];
        do{
            int x2,y2;
            if(get(unit2[i])){
                //角色存在
                if(!(get(unit2[i]+0xC)&state_dead)){   //未死亡
                    u8  status = (getb(unit2[i]+0x30)&0xf);
                    if(status==status_partial_rain||status==status_partial_snow){
                        //局部雨和局部雪
                        x2 = getb(unit2[i]+0x10);
                        y2 = getb(unit2[i]+0x11);
                        #if 0
                        //只能处理相隔距离，不能很好处理局部地区
                        u32 dis2 = x2+y2;
                        int d_ = (int)dis2-(int)dis;
                        if(d_<0){
                            d_ = -d_;
                        }
                        if(d_<=range){
                            return get(get(unit+4)+0x3c);   //雨天
                        }
                        #else
                        status -= (status_partial_rain);
                        status += 1;


                        int mx,my;
                        int range = 3;//范围是3
                        //剩下的就是处理状态动画了
                        for(my=-range;my<range;my++){
                            for(mx=-range;mx<range;mx++){
                                //在15格之内
                                int x3 = x2 + mx;
                                int y3 = y2 + my;
                                if(abs(x3-x)<=15 && abs(y3-y)<=15){
                                    set_local_weather(x3-x,y3-y,status);
                                }
                            }
                        }
                        #endif
                    }
                }
            }
            i++;
        }while(i<=max);
    }
    if(local_weather->x>=0){
        //当前有局部天气
        local_weather->x = x;
        local_weather->y = y;
    }

    return get(get(unit+4)+0x38);        //普通天气
}

#if 1
//实时判断是局部天气效果?
//在一些情况下，骑兵9移动，可以一些冲进局部雨天天气的单位
#define nasm(n) asm(n); asm("\n");

u32 _80007B0Hack(u32 r0,u32 r1,u32 r2,u32 *sp){
    #define r7 4
    #define r8 5
    #define pc 6
    u32     r3 = get(sp[3]);
    int x = r1   + 0;//getb(r3);
    int y = r2   + 0;//getb(r3+1);
    //log->data[log->num++] = x|(y<<8);
    //int addr = 0x202e4d8;
    //addr = get(sp[pc]+(0x800077C-0x80007B4));
    //sp[r7] = getb(get(sp[r7])+(r2<<2));
    #if 0
    //原程序处理
    sp[r8] = 0x3004B50;
    #else
    if(local_weather->x>=0){
        int t = get_local_weather(x,y);
        //局部天气限制移动
        u32 move_ptr = local_weather->moves[t];
        if(move_ptr){
            sp[r8] = move_ptr;
        }
        else{
            sp[r8] = 0x3004b50;
        }
    }
    else{
        //没有局部天气效果
        sp[r8] = 0x3004B50;
    }
    #endif
    //log->data[log->num++] = r0|(r1<<8);
};

void _80007B0(){
    nasm("mov r0,r0\n");
    nasm(".arm")
    nasm("_80007B0JJ:");
    nasm("ldr r7,[r7]");
    nasm("ldr r7,[r7,r2,lsl #2]")
    nasm("ldrb r7,[r7,r1]")
    //nasm("ldr r8,=0x3004B50")
    nasm("push {r0,r1,r2,r3,r7,r8,r9,r12,lr}");
    nasm("mov r3,sp");
    nasm("bl _80007B0Hack");
    nasm("pop {r0,r1,r2,r3,r7,r8,r9,r12,lr}");
    //nasm("ldr r9,=0x80007B4\n");
    nasm("bx r9");

    nasm(".section	.0x080007A4,\"a\",%progbits")
	nasm(".align	4")
	nasm(".type	    _80007A0_, %object")
    nasm("_80007A0_:");      /*mov */
    nasm(".arm");      //arm代码
    #if 0
    nasm("ldr r8,_80007B0_J");
    nasm("bx r8");      //跳转到目标函数
    #else
    nasm("add   r9,pc,#0x10-8");
    nasm("ldr   r8,_80007B0_J");
    nasm("bx    r8");
    #endif
    nasm("_80007B0_J: .int _80007B0JJ");
    nasm(".size _80007A0_,. - _80007A0_");
    nasm(".text");
}

#endif
